home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / Interapplication Communication / AECDEV⁄AEDAEMON / AEDaemonPPCStuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-09  |  8.5 KB  |  238 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #   Apple Developer Technical Support
  4. #
  5. #   AEDeamon
  6. #   A small faceless background-only application
  7. #
  8. #   AEDeamonPPCStuff.c  -   C Source
  9. #
  10. #   Copyright © 1991 Apple Computer, Inc.
  11. #   All rights reserved.
  12. #
  13. #   Versions:   
  14. #               1.0               08/91       C.K. Haun <TR>
  15. #   
  16. #   Components:
  17. #                           AEDeamonMain.c
  18. #                           AEDeamonAEvents.c
  19. #                            AEDeamonPPCStuff.c
  20. --------------------------------------------------------------------------------*/
  21. /*------------------------------------------------------------------------------
  22. #    This file contains all the PPC stuff for the AEDeamon.  It reads the AppleEvent
  23. #    data from the PPC channel, puts it in an AEDesc, and fires it for AESend.
  24. #    That's all it does.  But _not_ all it could do.  If the sender wanted a reply,
  25. #    the Deamon could send the reply back through the same channel the event came through.
  26. #    This sample does the minimum, but you can expand it reasonably easily to 
  27. #    give full AppleEvent support to any DA/INIT/CDEV/DRIVER you want.
  28. --------------------------------------------------------------------------------*/
  29.  
  30.  
  31. #include "AEDaemon.h"
  32.  
  33.  
  34. Handle dataHandle;
  35. OSType gTypeTag;
  36. Boolean gMore;
  37. PPCPortRec ourPort;
  38. PPCPortRefNum ourPortID;
  39. MyPPCRecPtrDeamon ourPPCPtr;
  40. PPCPortRec myPortName;
  41. LocationNameRec myLoc;
  42. Ptr readBuffer;
  43. Handle eventData;
  44. #define kGenStrings 128
  45. #define kPortName 132
  46. extern Boolean gReadPending;
  47. extern unsigned long gMySleep;
  48.  
  49. /* InformTheWorld opens our PPC port, and posts a PPCInform so other folks */
  50. /* can connect to us */
  51. Boolean InformTheWorld(void)
  52. {
  53.     Boolean result = false;
  54.     
  55.     OSErr myErr = noErr;
  56.     PPCOpenPBPtr localPtr;
  57.     localPtr = (PPCOpenPBPtr)ourPPCPtr;                     /* makes things more readable */
  58.     /* get a buffer to read stuff into */
  59.     /* first get a port, if we don't already have one */
  60.     if (ourPortID == nil) {
  61.         myErr = OpenAPort((PPCOpenPBPtr)ourPPCPtr);
  62.         if (myErr)
  63.             return(false);                                  /* we failed, die */
  64.         
  65.         ourPortID = localPtr->portRefNum;
  66.     }
  67.     DoInform((PPCInformPBPtr)ourPPCPtr);
  68.     
  69.     return(result);
  70. }
  71.  
  72. /* OpenAPort, uhhh, opens a port.  Opens our PPC port for others */
  73. /* to talk to us through */
  74. OSErr OpenAPort(PPCOpenPBPtr myPort)
  75. {
  76.     myPortName.nameScript = 0;
  77.     GetIndString(&myPortName.name,kGenStrings,kPortName);
  78.     myPortName.portKindSelector = ppcByCreatorAndType;
  79.     myPortName.u.port.creator = 'MOOB';
  80.     myPortName.u.port.type = 'APPL';
  81.     myPort->ioCompletion = (PPCCompProcPtr)OpenComplete;
  82.     
  83.     myPort->serviceType = ppcServiceRealTime;               /* only valid one under 7.0 */
  84.     myPort->resFlag = 0;
  85.     myPort->portName = &myPortName;
  86.     myPort->locationName = &myLoc;
  87.     myPort->networkVisible = false;                         /* NO, I don't want others using this service */
  88.     myLoc.locationKindSelector = ppcNoLocation;
  89.     
  90.     /* open syncrnouls */
  91.     return(PPCOpen(myPort, true));
  92.     
  93. }
  94.  
  95. /* PPCOpenPort */
  96.  
  97. /* DoInform posts a PPCInform, telling the world that we are ready to */
  98. /* accept data through our PPC channel */
  99. Boolean DoInform(PPCInformPBPtr p)
  100. {
  101.     
  102.     p->ioCompletion = (PPCCompProcPtr)InformComplete;
  103.     /* port reference number is already set in the Parameter Block */
  104.     /* most of this junk is already set */
  105.     p->portName = nil;
  106.     p->locationName = nil;
  107.     p->userName = nil;
  108.     p->autoAccept = true;   /* if true session will be accepted automatically */
  109.     /* instead of having to go through a PPCAccept.  I'm doing this primarly */
  110.     /* because this deamon is not network visible, so I don't thing anyone */
  111.     /* will be playing hijinks on us.  */
  112.     if (PPCInform(p, true) != noErr) {       
  113.         return false;
  114.     } else
  115.         return true;
  116. }
  117.  
  118. /* DoInform */
  119.  
  120. /* CloseOffTheWorld shuts things down when this app quits */
  121. void CloseOffTheWorld(void)
  122. {
  123.     PPCClosePBPtr closeRec = NewPtrClear(sizeof(PPCClosePBRec));
  124.     closeRec->ioCompletion = nil;
  125.     closeRec->ioResult = 0;
  126.     closeRec->portRefNum = ourPortID;
  127.     PPCClose(closeRec, false);
  128.     DisposPtr((Ptr)closeRec);
  129.     
  130.     
  131. }
  132.  
  133. /* I could post the PPC inform from here, but I decided not to in this case.  */
  134. /* Why?  I'm not sure. */
  135. void OpenComplete(PPCInformPBPtr p)
  136. {
  137. #pragma unused (p)
  138.     /* do nothing */
  139.     
  140. }
  141.  
  142. /* When this InformCompletion routine is hit, that means that someone has */
  143. /* invoked a PPCStart on our port.  Since we automatically accepted it, we */
  144. /* will begin reading from here.  If we wanted to authenticate, we'd do a PPCAccept */
  145. /* here (if we wanted to accept) and then start the read from the */
  146. /* PPCAccept completion routine. */
  147. void InformComplete(PPCReadPBPtr p)
  148. {
  149.     /* Start reading Bucky */
  150.     
  151.     p->ioCompletion = (PPCCompProcPtr)ReadComplete;
  152.     p->bufferPtr = readBuffer;
  153.     p->bufferLength = kOneK;
  154.     gMySleep = 1; /* bump the sleep time down so we can start processing faster */
  155.     /* so we can process the data after it's read */
  156.     /* since we won't go through WaitNextEvent and see the completion flag unless */
  157.     /* we bump the sleep time down a bit */
  158.     PPCRead((PPCReadPBPtr)p, true);
  159. }
  160.  
  161. /* When we hit this completion routine, it means one of two things; */
  162. /* 1) We are all done reading, and we are ready to send the event */
  163. /* or */
  164. /* 2) We've filled our PPC buffer (rememeber, it was only one K ) */
  165. /* and we need to swap that data to a safe place and read again */
  166. void ReadComplete(PPCReadPBPtr p)
  167. {
  168.     /* read completeed, deal with it */
  169.     gReadPending = true;
  170.     gMore = p->more;
  171.     gTypeTag = p->blockType;
  172.     gMySleep = 0;
  173. }
  174.  
  175. /* this processes the result of the last async read, and re-reads if */
  176. /* theres more data to get */
  177. /* It also checks to see if this is data we understand. In this case, MAVT type */
  178. /* data (which means My AppleeVenT), I set this type in the PPCWrite block */
  179. /* elsewhere.  If you don't do this, bad things will happen when you try */
  180. /* and do an AESend on data someone else sent */
  181. void CollectLastData(void)
  182. {
  183.     unsigned long currentSize;
  184.     AppleEvent theEvent;
  185.     PPCReadPBPtr localPtr = (PPCReadPBPtr)ourPPCPtr;
  186.     if (gMore) {
  187.         /* we need to move the current data into another buffer, and then read again */
  188.         currentSize = GetHandleSize(dataHandle);
  189.         SetHandleSize(dataHandle, currentSize + localPtr->actualLength);
  190.         HLock(dataHandle);
  191.         BlockMove(readBuffer, (*dataHandle) + currentSize, localPtr->actualLength);
  192.         HUnlock(dataHandle);
  193.         localPtr->ioCompletion = (PPCCompProcPtr)ReadComplete;
  194.         localPtr->bufferPtr = readBuffer;
  195.         localPtr->bufferLength = kOneK;
  196.         /* read more */
  197.         PPCRead((PPCReadPBPtr)localPtr, true);
  198.         
  199.     } else {
  200.         /* now we need to send the thing.  So send it, then re-post the inform */
  201.         /* there's no more, but we need to move what we have */
  202.         /* same as before */
  203.         if (gTypeTag == kMyTypeOfData) {
  204.             currentSize = GetHandleSize(dataHandle);
  205.             SetHandleSize(dataHandle, currentSize + localPtr->actualLength);
  206.             HLock(dataHandle);
  207.             BlockMove(readBuffer, (*dataHandle) + currentSize, localPtr->actualLength);
  208.             HUnlock(dataHandle);
  209.             
  210.             PPCEnd((PPCEndPBPtr)localPtr, false);
  211.             
  212.             gReadPending = false;
  213.             gMySleep = 200;                                 /* back to sleep */
  214.             /* now send the event we've so laboriously xfered */
  215.             /* you'll notice here that I am setting the descriptor type */
  216.             /* to 'aevt' and using some default interaction, reply, and */
  217.             /* timeout values.  To be more flexible, you should pass all these paramters */
  218.             /* as a 'header' block through PPC, see the Read Me file for more details */
  219.             /* I am doing this here for simpliciites sake */
  220.             theEvent.descriptorType = kCoreEventClass;
  221.             theEvent.dataHandle = dataHandle;
  222.             AESend(&theEvent, nil, kAECanInteract + kAENoReply + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout,
  223.                    nil, nil);
  224.             /* so we just sent the event. Normally, you'd call AEDisposeDesc on this thing, */
  225.             /* but in this case since it's our handle made by us, I'll just set it's size */
  226.             /* back to zero */
  227.         } else {
  228.             /* it was not my data type, so end the session */
  229.             PPCEnd((PPCEndPBPtr)localPtr, false);
  230.         }
  231.         SetHandleSize(dataHandle, 0);
  232.         /* Now we re-inform, we're ready for another message */
  233.         InformTheWorld();
  234.     }
  235. }
  236.  
  237.  
  238.